/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#import "MessagesDataSource.h"
#import "MailboxItem.h"
#import "MessageHeader.h"

#import "nsIMsgFolder.h"
#import "nsIMsgWindow.h"
#import "nsMsgBaseCID.h"
#import "nsIMsgHdr.h"

#import "nsISimpleEnumerator.h"

// I should probably change these soon.
static NSString* const kIsReadColumnIdentifier = @"IsReadIdentifier";
static NSString* const kFromColumnIdentifier = @"FromIdentifier";
static NSString* const kSubjectColumnIdentifier = @"subjectIdentifier";
static NSString* const kDateColumnIdentifier = @"DateIdentifier";

@interface MessagesDataSource(Private)

/**
 * This utility function exists so that we can find out
 * where the requested index item is really at. For example,
 * if the array is sorted, the item will be at the opposite 
 * end of the array. This is here to keep simplicity in MWC.
 * @param aIndex - The requested index.
 * @return The real index of the item in the array.
 */
-(int)currentItemIndexForIndex:(int)aIndex;

/**
 * This utility function finds the index of the given message header.
 * @param aMessageHeader The message header to search for.
 * @return The index of the passed in message header.
 */
-(int)indexOfMessageHeader:(MessageHeader*)aMessageHeader;

-(void)removeMessageHeaderAtIndex:(int)aIndex;

@end

@implementation MessagesDataSource

-(id)init
{
  if ((self = [super init]))
  {
    mMessages = [[NSMutableArray alloc] init];
    mIsSortDescending = NO;
  }
  
  return self;
}

-(void)dealloc
{
  [mMessages release];
  [super dealloc];
}

-(void)createMessageListForHeaderEnum:(nsISimpleEnumerator*)aSimpleMsgEnum
{
  if (!aSimpleMsgEnum)
    return;
    
  if ([mMessages count] > 0)
    [mMessages removeAllObjects];
  
  nsresult rv;
  PRBool enumHasMore = PR_FALSE;
  while (NS_SUCCEEDED(aSimpleMsgEnum->HasMoreElements(&enumHasMore)) && enumHasMore)
  {
    nsCOMPtr<nsISupports> item;
    aSimpleMsgEnum->GetNext(getter_AddRefs(item));
    
    nsCOMPtr<nsIMsgDBHdr> msgDBHdr = do_QueryInterface(item, &rv);
    if (NS_SUCCEEDED(rv))
    {
      MessageHeader* curMessage = [[MessageHeader alloc] initWithMsgDBHdr:msgDBHdr];
      [mMessages addObject:curMessage];
      [curMessage release];
    }
  }
}

-(void)clearMessages
{
  [mMessages removeAllObjects];
}

-(unsigned int)messageIndexForMessageId:(NSString*)aMessageID
{
  unsigned int i = 0;
  for (; i < [mMessages count]; i++)
  {
    MessageHeader* curHeader = [self messageHeaderAtIndex:i];
    if ([aMessageID isEqualToString:[curHeader messageId]])
      return i;
  }
  
  return 0;
}

-(unsigned int)messageCount
{
  return [mMessages count];
}

-(void)sortUsingSelector:(SEL)aSelector
{
  if (aSelector == mCurrentSortSelector)
  {
    mIsSortDescending = !mIsSortDescending;
    return;
  }
  
  [mMessages sortUsingSelector:aSelector];
  mCurrentSortSelector = aSelector;
  mIsSortDescending = NO;
}

-(BOOL)isSortedDescending
{
  return mIsSortDescending;
}

-(int)currentItemIndexForIndex:(int)aIndex
{
  return (mIsSortDescending ? [mMessages count] - 1 - aIndex : aIndex);
}

-(int)indexOfMessageHeader:(MessageHeader*)aMessageHeader
{
  return [self currentItemIndexForIndex:[mMessages indexOfObject:aMessageHeader]];
}

-(MessageHeader*)messageHeaderAtIndex:(int)aIndex
{
  return [mMessages objectAtIndex:[self currentItemIndexForIndex:aIndex]];
}

-(void)removeMessageHeaderAtIndex:(int)aIndex
{
  [mMessages removeObjectAtIndex:[self currentItemIndexForIndex:aIndex]];
}

@end
